package com.backend.server.config.filter;

import com.common.server.common.BaseResponse;
import com.common.server.common.ErrorCode;
import com.common.server.common.ResultUtils;
import com.common.server.constant.UserConstant;
import com.common.server.entity.user.UserInfo;
import com.common.server.exception.ThrowUtils;
import com.common.server.utils.JwtUtil;
import com.common.server.utils.RedisUtil;
import com.google.gson.Gson;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashSet;
import java.util.Set;

/**
 * ClassName: WebFilter
 * Package: com.backend.server.config.filter
 * Description:
 *
 * @Author Memory
 * @Create 2024/12/30 13:33
 * @Version 1.0
 */

// @Component
@Slf4j
public class WebFilter implements Filter {
    @Resource
    private JwtUtil jwtUtil;
    @Resource
    private RedisTemplate redisTemplate;
    // 假设这些路径不需要 token 验证
    private final Set<String> whiteListPaths = new HashSet<>();

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        // 初始化白名单路径，可以从配置文件中读取
        whiteListPaths.add(UserConstant.USER_LOGIN_WHITE_PATH);  // 登录路径
        whiteListPaths.add(UserConstant.USER_REGISTER_WHITE_PATH);  // 注册路径
        whiteListPaths.add(UserConstant.USER_GET_LOGIN_WHITE_PATH);  // 当前登录用户
        whiteListPaths.add(UserConstant.SWAGGER_DOC_WHITE_PATH);  // Swagger UI文档页面
        whiteListPaths.add(UserConstant.SWAGGER_RESOURCES_WHITE_PATH);  //  Swagger资源路径
        whiteListPaths.add(UserConstant.SWAGGER_RESOURCES_CONFIGURATION_UI_WHITE_PATH);  // Swagger UI配置资源路径
        whiteListPaths.add(UserConstant.SWAGGER_API_DOCS_WHITE_PATH);  // Swagger API文档JSON资源路径
        // 可以添加更多路径
        log.info("初始化白名单路径：{}", whiteListPaths);
    }

    Gson gson = new Gson();

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        HttpServletResponse httpResponse = (HttpServletResponse) response;
        // 检查请求路径是否在白名单中
        String requestURI = httpRequest.getRequestURI();
        if (whiteListPaths.contains(requestURI)) {
            chain.doFilter(request, response);
            return;
        }
        if (requestURI.startsWith("/backend-server/webjars")) {
            // 放行请求
            chain.doFilter(request, response);
            return;
        }

        log.info("请求路径：{}", requestURI);
        // 解析并验证 token
        String token = httpRequest.getHeader("Authorization");
        log.info("token：{}", token);
        if (StringUtils.isBlank(token)) {
            log.error("token为空");
            httpResponse.addHeader("message", "token为空");
            httpResponse.setContentType("application/json");
            httpResponse.setCharacterEncoding("UTF-8");
            httpResponse.setStatus(401);
            // 创建 JSON 响应体
            String jsonResponse = "{\"code\": \"401\", \"data\": null, \"message\": \"Token 为空\"}";
            try (PrintWriter out = httpResponse.getWriter()) {
                out.write(jsonResponse);
            } catch (IOException e) {
                log.error("Failed to write response", e);
            }
            return;
        }
        token = token.substring(7);
        boolean verifyToken = jwtUtil.verifyToken(token);
        if (!verifyToken) {
            log.error("当前token无效或已过期");
            httpResponse.addHeader("message", "当前token无效或已过期");
            httpResponse.setContentType("application/json");
            httpResponse.setCharacterEncoding("UTF-8");
            httpResponse.setStatus(401);
            // 创建 JSON 响应体
            String jsonResponse = "{\"code\": \"401\", \"data\": null, \"message\": \"当前token无效或已过期\"}";
            try (PrintWriter out = httpResponse.getWriter()) {
                out.write(jsonResponse);
            } catch (IOException e) {
                log.error("Failed to write response", e);
            }
            return;
        }
        // 从redis中获取 token
        String userId = JwtUtil.getSubjectFromToken(token);
        String role = JwtUtil.getClaimFromToken(token, "role");
        Object object = redisTemplate.opsForValue().get(String.format(UserConstant.TOKEN__KEY, userId, role));
        if (ObjectUtils.isEmpty(object)) {
            log.error("用户未登录");
            httpResponse.addHeader("message", "用户未登录");
            httpResponse.setContentType("application/json");
            httpResponse.setCharacterEncoding("UTF-8");
            httpResponse.setStatus(401);
            // 创建 JSON 响应体
            String jsonResponse = "{\"code\": \"401\", \"data\": null, \"message\": \"用户未登录\"}";
            try (PrintWriter out = httpResponse.getWriter()) {
                out.write(jsonResponse);
            } catch (IOException e) {
                log.error("Failed to write response", e);
            }
            return;
        }
        // 放行
        chain.doFilter(request, response);
    }
}